#include "DefineCommon.h"
#include "DefineLibCommon.h"
#include "EItemMeta.h"
#include "EItemMetaProperty.h"
#include "EItemTest.h"
#include "EVariant.h"
#include <EItemMetaFunction.h>
#include <cstdarg>
#include <cstdint>

/**class member functions*/
class EItemTestAutogen_Fun_testAdd : public EItemMetaFunction
{
    virtual void callInternal(intptr_t itemPtr, ... )
    {
        va_list args;
        va_start(args, itemPtr);
        EVariant* valueReturn = va_arg(args, EVariant*);
        EVariant* valueV1 = va_arg(args, EVariant*);
        EVariant* valueV2 = va_arg(args, EVariant*);

        EItemTest* itemSubPtr = (EItemTest*)this->getOwner();
        itemSubPtr->uiFun_testAdd(
                valueV1->value_double,
                valueV2->value_double
                        );
        va_end(args);
    }
};

/**class set/get property functions*/
void EItemTestAutogen_Fun_OnSet_testDouble(intptr_t owner, const EVariant& value)
{
    EItemTest* itemSubPtr = (EItemTest*)owner;
    itemSubPtr->ui_testDouble = value.value_double;
    itemSubPtr->OnSet_testDouble(value.value_double);
}

void EItemTestAutogen_Fun_OnGet_testDouble(intptr_t owner, EVariant& value)
{
    EItemTest* itemSubPtr = (EItemTest*)owner;
    itemSubPtr->OnGet_testDouble(value.value_double);
}

/**Function that create EItemMetaPtr*/
EItemMetaPtr EItemTestAutogen_createMeta(EItem* itemPtr)
{
    ELOG_DEBUG("----------");
    EItemTest* itemSubPtr = (EItemTest*)itemPtr;
    EItemMetaPtr metaPtr = NewSmartPtr(EItemMeta)();
    metaPtr->setClassName("EItemTest");

    /**add class member function to metaPtr*/
    {
        EItemMetaFunctionPtr fun = NewSmartPtr(EItemTestAutogen_Fun_testAdd)();
        fun->setName("testAdd");
        fun->setFunType(EItemMetaFunction::FunType::CLASS_MEMBER);
        fun->setOwner((intptr_t)itemPtr);
        
        {
            EItemMetaPropertyPtr prop = NewSmartPtr(EItemMetaProperty)();
            prop->name = "returnValue";
            prop->typeName = "empty";
            fun->setReturnProperty(prop);
        }

        {
            EItemMetaPropertyPtr prop = NewSmartPtr(EItemMetaProperty)();
            prop->name = "v1";
            prop->typeName = "Double";
            fun->addProperty(prop);
        }

        {
            EItemMetaPropertyPtr prop = NewSmartPtr(EItemMetaProperty)();
            prop->name = "v2";
            prop->typeName = "Double";
            fun->addProperty(prop);
        }
        
        metaPtr->addFunction(fun);
    }

    /**add properties to metaPtr*/
    EVariant tempValue;

    /**property ui_testInt*/
    {
        tempValue = itemSubPtr->ui_testInt;

        EItemMetaPropertyPtr prop = NewSmartPtr(EItemMetaProperty)();
        prop->name = "testInt";
        prop->typeName = "Int";
        prop->value = tempValue;
        metaPtr->addProperty(prop);
    }
    
    /**property ui_testDouble*/
    {
        tempValue = itemSubPtr->ui_testDouble;

        EItemMetaPropertyPtr prop = NewSmartPtr(EItemMetaProperty)();
        prop->name = "testDouble";
        prop->typeName = "Double";
        prop->value = tempValue;
        prop->maxValue = itemSubPtr->ui_testDouble_max;
        prop->minValue = itemSubPtr->ui_testDouble_min;
        prop->m_owner = (intptr_t)itemSubPtr;
        prop->m_funSetProperty = EItemTestAutogen_Fun_OnSet_testDouble;
        prop->m_funGetProperty = EItemTestAutogen_Fun_OnGet_testDouble;

        metaPtr->addProperty(prop);
    }
    
    /**property ui_testBool*/
    {
        tempValue = itemSubPtr->ui_testBool;

        EItemMetaPropertyPtr prop = NewSmartPtr(EItemMetaProperty)();
        prop->name = "testBool";
        prop->typeName = "Bool";
        prop->value = tempValue;
        metaPtr->addProperty(prop);
    }

    /**property ui_testVec3*/
    {
        tempValue = itemSubPtr->ui_testVec3;

        EItemMetaPropertyPtr prop = NewSmartPtr(EItemMetaProperty)();
        prop->name = "testVec3";
        prop->typeName = "Vec3";
        prop->value = tempValue;
        metaPtr->addProperty(prop);
    }

    /**property ui_testVec4*/
    {
        tempValue = itemSubPtr->ui_testVec4;

        EItemMetaPropertyPtr prop = NewSmartPtr(EItemMetaProperty)();
        prop->name = "testVec4";
        prop->typeName = "Vec4";
        prop->value = tempValue;
        metaPtr->addProperty(prop);
    }

    /**property ui_testMatrix*/
    {
        tempValue = itemSubPtr->ui_testMatrix;

        EItemMetaPropertyPtr prop = NewSmartPtr(EItemMetaProperty)();
        prop->name = "testMatrix";
        prop->typeName = "Matrix_4X4";
        prop->value = tempValue;
        metaPtr->addProperty(prop);
    }

    /**property ui_testString*/
    {
        tempValue = itemSubPtr->ui_testString;

        EItemMetaPropertyPtr prop = NewSmartPtr(EItemMetaProperty)();
        prop->name = "testString";
        prop->typeName = "String";
        prop->value = tempValue;
        metaPtr->addProperty(prop);
    }

    return metaPtr;
}

/**Called by EItemXXX's construct function*/
void EItemTestAutogen_construct(EItem* itemPtr)
{
    itemPtr->setFunCreateMeta(EItemTestAutogen_createMeta);
}

/**class factory functions*/
class EItemTestAutogen_Fun_factory : public EItemMetaFunction
{
    virtual void callInternal(intptr_t itemPtr, ... )
    {
        va_list args;
        va_start(args, itemPtr);
        EVariant* valueReturn = va_arg(args, EVariant*);

        EItemTest* newPtr = new EItemTest();
        *valueReturn = (intptr_t)newPtr;

        va_end(args);
    }
};

COMMON_DLL EItemMetaFunctionPtr EItemTestAutogen_getFactoryFun()
{
    EItemMetaFunctionPtr fun = NewSmartPtr(EItemTestAutogen_Fun_factory)();

    fun->setName("EItemTestAutogen_Fun_factory");
    fun->setFunType(EItemMetaFunction::FunType::CONSTRUCTOR);


    return fun;
}
    
